// Author: Domien Nowicki

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QStyleOption>

#include "MapProvinceItem.h"
#include "MapPointItem.h"
#include "MapWidget.h"

using std::min;
using std::max;


MapProvinceItem::MapProvinceItem(MapWidget *mapView, const std::string& name): map(mapView), Province(name)
{
	// Set province to be just above a land, and below a point item
	setZValue(PROVINCEZ);

	// Set name hint when hovering over a province
	setToolTip(GetName().c_str());
}

MapProvinceItem::MapProvinceItem(const MapProvinceItem& rhs): map(rhs.map), Province(rhs.GetName())
{
	setZValue(PROVINCEZ);
	Copy(rhs);
	setToolTip(GetName().c_str());
}

MapProvinceItem::MapProvinceItem(MapWidget *mapView, const Province& rhs): map(mapView), Province(rhs.GetName())
{
	setZValue(PROVINCEZ);
	Copy(rhs);
	setToolTip(GetName().c_str());
}


MapProvinceItem::~MapProvinceItem()
{
}

QRectF MapProvinceItem::boundingRect() const
{
	// Return the bounding rectangle of this item
	std::list<Point*>::const_iterator pointIt;
	bool gotFirstPoint = false;

	int xmin = 0;
	int xmax = 0;
	int ymin = 0;
	int ymax = 0;


	for(pointIt = points.begin(); pointIt != points.end(); ++pointIt)
	{
		const Point* point = *pointIt;

		// Initialize step
		if (!gotFirstPoint)
		{
			gotFirstPoint = true;

			xmin = xmax = point->GetX();
			ymin = ymax = point->GetY();
		}
		else
		{
			xmin = min(xmin, point->GetX());
			xmax = max(xmax, point->GetX());
			ymin = min(ymin, point->GetY());
			ymax = max(ymax, point->GetY());
		}
	}

	int adjust = PROVINCEADJUST;

	// Take into account a little adjustment
	return QRectF(xmin - adjust, ymin - adjust, (xmax-xmin) + adjust*2, (ymax-ymin) + adjust*2);
}

const QPolygon& MapProvinceItem::GetPolygon() const
{
	return poly;
}

QPainterPath MapProvinceItem::shape() const
{
	// Return the shape of this item
	QPainterPath temp;

	temp.addPolygon(poly);
	temp.closeSubpath();
	return temp;
}

void MapProvinceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	QColor qcolor;

	Color color = GetColor();

	// If color is an erase color
	if (color.IsColor())
	{
		// Convert Color to QColor
		qcolor = QColor(color.GetRed(), color.GetGreen(), color.GetBlue());
	}
	else
	{
		// Set province to be painted in a transparent color
		qcolor = QColor(0,0,0,0);
	}
	// Draw the polygon which represents this province
	painter->setBrush(qcolor);
	painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
	painter->drawPolygon(poly);
}

void MapProvinceItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
	// Notify listeners that this province was clicked
	emit clickedProvince(this);

	// Schedule a paint event
	update();
}

Point* MapProvinceItem::InsertPoint(MapPointItem *item)
{
	// Connect the scene signal so that childs can add themself to the scene
	QObject::connect(this, SIGNAL(parentAddedToScene(QGraphicsScene*)), item, SLOT(AddToScene(QGraphicsScene*)));

	// Add this item to the scene
	AddToScene(scene(), item);

	// Add the point to the polygon
	poly.append(QPoint( item->GetX(), item->GetY()));

	// Insert the point
	return Province::InsertPoint(item);
}

void MapProvinceItem::AddToScene(QGraphicsScene *newScene, QGraphicsItem *item)
{
	// Add item to scene, or add self to scene if item is null
	if (newScene)
	{
		if (0 == item)
			item = this;

		// Add the item to the scene
		newScene->addItem(item);

		// Tell listeners that their parent was added to a scene
		emit parentAddedToScene(newScene);
	}
}

Point* MapProvinceItem::InsertNewPoint(int x, int y)
{
	return InsertPoint( new MapPointItem(map, x, y) );
}

Point* MapProvinceItem::InsertNewPoint(const Point& point)
{
	return InsertPoint( new MapPointItem(map, point) );
}

void MapProvinceItem::SetColor(Color newColor)
{
	// Schedule a paint event
	update();

	Province::SetColor(newColor);
}

void MapProvinceItem::SetName(const std::string& name)
{
	Province::SetName(name);

	// Set new tooltip
	setToolTip(GetName().c_str());
}

void MapProvinceItem::SetCursor(const QCursor& cursor)
{
	setCursor(cursor);
}


